#include <RX8025.h>
#include <Wire.h>
#include <NetTime.h>

#define RX8025_address 0x32

RX8025 rxTime; // 常用时间对象，避免重复生成

#define bcd2bin(val) ((val) - 6 * ((val) >> 4))
#define bin2bcd(val) ((val) + 6 * ((val) / 10))

// uint8_t bcd2bin(uint8_t val)
// {
//     return val - 6 * (val >> 4);
// }

// uint8_t bin2bcd(uint8_t val)
// {
//     return val + 6 * (val / 10);
// }

void RX8025::begin()
{
    Wire.begin();
    Wire.beginTransmission(RX8025_address);
    // clear power on reset flag, set to 24hr format
    Wire.write(0xe0);
    Wire.write(0x20);
    Wire.write(0x00);
    Wire.endTransmission();

    // 借用RX8025定时寄存器记录最后同步日期
    // 日期变化则自动同步时间
    uint8_t mDay = getData(NOW_MDAY);
    if(mDay != getData(SYNC_DAY))
    {
        setData(SYNC_DAY, mDay);
        syncTime();
    }

}

int RX8025::getHMTime()
{
    int h, m;
    Wire.beginTransmission(RX8025_address);
    Wire.write(0x01);
    Wire.endTransmission();
    Wire.requestFrom(RX8025_address, 2);
    m = Wire.read();
    h = Wire.read();
    Wire.endTransmission();
    return (h << 8) | m;
}

uint8_t RX8025::getData(uint8_t regaddr)
{
    // 使用指定的地址开始向I2C从设备进行传输。
    Wire.beginTransmission(RX8025_address);
    Wire.write(regaddr); //(regaddr);
    // 停止与从机的数据传输
    Wire.endTransmission();
    // 由主设备用来向从设备请求字节。
    Wire.requestFrom(RX8025_address, 1);
    // 读取数据
    return Wire.read();
}

void RX8025::setData(uint8_t regaddr, uint8_t value)
{
    // 使用指定的地址开始向I2C从设备进行传输。
    Wire.beginTransmission(RX8025_address);
    Wire.write(regaddr);
    Wire.write(value);
    // 停止与从机的数据传输
    Wire.endTransmission();
}

void RX8025::getTime(TIME_TM *tm)
{
    unsigned char i = 0;
    unsigned char val[7];

    Wire.beginTransmission(RX8025_address);
    Wire.write(0x00);
    Wire.endTransmission();
    Wire.requestFrom(RX8025_address, 7);
    while (Wire.available())
    {
        val[i] = Wire.read();
        i++;
    }
    Wire.endTransmission();

    // 星期几由第几位为零表示，需转换为0-6
    tm->tm_wday = 0;
    while ((val[3] >>= 1) != 0)
        tm->tm_wday++;

    tm->tm_year = bcd2bin(val[6] & 0xff) + 100; // 00-99 ：+2000-1900
    tm->tm_mon = bcd2bin(val[5] & 0x1f) - 1;    // 1-12
    tm->tm_mday = bcd2bin(val[4] & 0x3f);
    // tm->tm_wday = bcd2bin(val[3] & 0x7f);
    tm->tm_hour = bcd2bin(val[2] & 0x3f);
    tm->tm_min = bcd2bin(val[1] & 0x7f);
    tm->tm_sec = bcd2bin(val[0] & 0x7f);
}

void RX8025::setTime(TIME_TM *tm)
{
    unsigned char val[7];

    val[6] = bin2bcd(tm->tm_year > 100 ? tm->tm_year - 100 : tm->tm_year);
    val[5] = bin2bcd(tm->tm_mon + 1);
    val[4] = bin2bcd(tm->tm_mday);
    val[3] = 1 << tm->tm_wday;
    val[2] = bin2bcd(tm->tm_hour);
    val[1] = bin2bcd(tm->tm_min);
    val[0] = bin2bcd(tm->tm_sec);

    Wire.beginTransmission(RX8025_address);
    Wire.write(0x00);
    for (unsigned char i = 0; i < 7; i++)
    {
        Wire.write(val[i]);
    }
    Wire.endTransmission();
}

time_t RX8025::getTime()
{
    TIME_TM tm;
    getTime(&tm);
    return mktime(&tm);
}

void RX8025::setTime(time_t now)
{
    TIME_TM *tm = gmtime(&now);
    setTime(tm);
}

void syncTime()
{
    // 网络对时需要从SD卡中读取wifi设置
    if(sdMount(true))
    {
        NetTime nt;
        time_t now = nt.getNetTime();
        if(now != 0)
        {
            rxTime.setTime(now);
        }
        sdMount(false);
    }
}